# -*- coding: utf-8 -*-
import random

from django.conf import settings
from django.template import RequestContext
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect, Http404 
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.core.urlresolvers import reverse
from django.views.generic.create_update import delete_object
from django.db.models import Count

from tagging.models import Tag, TaggedItem

from models import Project, Release, Screenshot, Video, Poll
from pygameweb.comments.views import comment_view
import forms


NEED_MEMBER_PERM = "You must be member of this project to do this"
NEED_ADMIN_PERM = "You must be admin of this project to do this"

def overview(request, tag=None, order_by="-last_edited"):
    values = {}
    if order_by == "name":
        projects = Project.objects.filter(hide=False, is_inactive=False)\
            .extra(select={"low_name": "lower(name)"}).order_by("low_name")
    elif order_by == "tag":
        if tag is None:
            # tag cloud is generated in the template
            return render_to_response('projects/overview.html',  
                               {"MIN_COUNT":settings.MIN_COUNT},
                               context_instance=RequestContext(request))
        else:
            tag = get_object_or_404(Tag, name=tag)
            values["tag"] = tag
            possible_projects = Project.objects.filter(hide=False, 
                                                       is_inactive=False)
            projects = TaggedItem.objects.get_by_model(possible_projects, tag)
            values["related_tags"] = Project.tag_objects.related(tag,
                                                   counts=True, 
                                                   min_count=settings.MIN_COUNT)
                                                   
    else:
        projects = Project.objects.filter(hide=False, is_inactive=False)\
                                                  .order_by(order_by)
    
    paginator = Paginator(projects, settings.PROJECTS_PER_PAGE)
    
    # Make sure page request is an int. If not, deliver first page.
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1
    
    # If page request (9999) is out of range, deliver last page of results.
    try:
        projects = paginator.page(page)
    except (EmptyPage, InvalidPage):
        projects = paginator.page(paginator.num_pages)

    values.update({"paginator":paginator, "page_obj":projects})
    return render_to_response('projects/overview.html',  
                               values, context_instance=RequestContext(request))


def random(request):
    try:
        p = Project.objects.filter(is_inactive=False, hide=False).order_by("?")[0]
        return HttpResponseRedirect(p.get_absolute_url())
    except IndexError:
        raise Http404


def detail(request, project_slug, release_slug="latest"):
    project = get_object_or_404(Project, slug=project_slug)
    if "potm-vote" in request.POST and request.user.is_authenticated():
        msg = Poll.objects.get_current().vote(request.user, project)
        if request.is_ajax():
            return HttpResponse("%s" % msg)
        else:
            request.user.message_set.create(message=msg)

    releases = Release.objects.filter(project=project).order_by("-created")
    if release_slug == "latest":
        if releases:
            release = releases[0]
        else:
            release = False
    else:
        try:
            release = Release.objects.get(project=project, slug=release_slug)
        except ObjectDoesNotExist:
            # say that the requested release was not found
            return HttpResponseRedirect(project.get_absolute_url())
    screenshots = Screenshot.objects.filter(project=project, public=True)
    priv_screenshots = Screenshot.objects.filter(project=project, public=False)
    won_potm = project.poll_set.all()
    values = {"project":project, "release":release, "releases":releases,
            "releasename_extra": "(latest)" if (releases and 
                                                release == releases[0]) else "",
            "screenshots":screenshots, "priv_screenshots":priv_screenshots,
            "can_vote": Poll.objects.get_current().can_vote(request.user),
            "won_potm":won_potm}
    values.update(comment_view(request, Project, object_id=project.id))
    values.update(project.get_perms(request.user))
    return render_to_response('projects/detail.html', values,
                               context_instance=RequestContext(request))
                               
@login_required                               
def create_or_edit_project(request, project_slug=None):
    if project_slug:
        action = "Edit project"
        project = get_object_or_404(Project, slug=project_slug)
        if not project.get_perms(request.user).get("has_admin_perm", False):
            request.user.message_set.create(message=NEED_ADMIN_PERM)
            return HttpResponseRedirect(project.get_absolute_url())            
        form_class = forms.ProjectEditForm
    else:
        action = "Create new project"
        project = None
        form_class = forms.ProjectCreationForm
    
    if request.method == 'POST':
        form = form_class(data=request.POST, files=request.FILES, instance=project)
        if form.is_valid():
            project = form.save(commit=False)
            if not project_slug:
                project.creator = request.user
            project.last_editor = request.user
            if "submit" in request.POST:
                project.save() 
                form.save_m2m()
                if not request.user in project.admins.all():
                    project.admins.add(request.user)
                    project.save()
                
                return HttpResponseRedirect(project.get_absolute_url())
            else:
                project.render_markup()
                preview = True
    else:
        form = form_class(instance=project)
        
    return render_to_response('projects/create_or_edit_project.html', locals(),
                               context_instance=RequestContext(request))
        
        
@login_required                               
def create_or_edit_release(request, project_slug, release_slug=None):
    project = get_object_or_404(Project, slug=project_slug)
    if release_slug:
        action = "Edit release"
        release = get_object_or_404(Release, project=project, slug=release_slug)
        if not project.get_perms(request.user).get("has_member_perm", False):
            request.user.message_set.create(message=NEED_MEMBER_PERM)
            return HttpResponseRedirect(release.version.get_absolute_url())
        form_class = forms.ReleaseEditForm
    else:
        action = "Release a new version"
        release = Release(project=project, creator=request.user)
        form_class = forms.ReleaseCreationForm
    
    if request.method == 'POST':
        form = form_class(data=request.POST, files=request.FILES, instance=release)
        if form.is_valid():
            release = form.save(commit=False)
        #    if not release_slug:
        #        release.creator = request.user
            release.last_editor = request.user
        #    release.project = project
            if "submit" in request.POST:
                release.save()
                if hasattr(form, 'save_m2m'):
                    form.save_m2m()
                return HttpResponseRedirect(reverse('view_release', 
                                                args=[project.slug, release.slug]))
            else:
                release.render_markup()
                preview = True
    else:
        form = form_class(instance=release)
        
    return render_to_response('projects/create_or_edit_release.html', locals(),
                               context_instance=RequestContext(request))        



@login_required                               
def create_or_edit_screenshot(request, project_slug, screenshot_slug=None):
    project = get_object_or_404(Project, slug=project_slug)
    if screenshot_slug:
        action = "Edit Screenshot"
        form_class = forms.ScreenshotEditForm
        screenshot = get_object_or_404(Screenshot, project=project,
                                       slug=screenshot_slug)
        if not project.get_perms(request.user).get("has_member_perm", False):
            request.user.message_set.create(message=NEED_MEMBER_PERM)
            return HttpResponseRedirect(project.get_absolute_url())
        
    else:
        action = "Create new Screenshot"
        form_class = forms.ScreenshotCreationForm
        screenshot = Screenshot(project=project, uploaded_by=request.user)
    
    if request.method == 'POST':
        form = form_class(data=request.POST, files=request.FILES, instance=screenshot)
        form.project = project
        if form.is_valid():
            screenshot = form.save(commit=False)
          #  if not screenshot_slug:
          #      screenshot.uploaded_by = request.user
          #  screenshot.project = project
            if "submit" in request.POST:
                screenshot.save()
                if hasattr(form, 'save_m2m'):
                    form.save_m2m()
                return HttpResponseRedirect(screenshot.get_absolute_url())
            else:
                preview = True
            
    else:
        form = form_class(instance=screenshot)
        
    return render_to_response('projects/create_or_edit_screenshot.html', locals(),
                               context_instance=RequestContext(request))    
                               

@login_required                               
def create_or_edit_video(request, project_slug, video_slug=None):
    project = get_object_or_404(Project, slug=project_slug)
    if video_slug:
        if not project.get_perms(request.user).get("has_member_perm", False):
            request.user.message_set.create(message=NEED_MEMBER_PERM)
            
        else:
            video = get_object_or_404(Video, slug=video_slug, project=project)
            if request.method == "POST" and  "update" in request.POST:
                video.sync_with_yt()
                video.save()
                request.user.message_set.create(message="Video infromation was updated.")
            else:
                request.user.message_set.create(message="Invalid data.")
        return HttpResponseRedirect(video.get_absolute_url())
    else:
        action = "Add new Video"
        form_class = forms.VideoCreationForm
        video = Video(project=project, added_by=request.user)
    
    if request.method == 'POST':
        form = form_class(data=request.POST, instance=video)
        form.project = project
        if form.is_valid():
            video = form.save()
            return HttpResponseRedirect(video.get_absolute_url())
            
    else:
        form = form_class(instance=video)
        
    return render_to_response('projects/create_or_edit_video.html', locals(),
                               context_instance=RequestContext(request))            
          
def detail_video(request, project_slug, video_slug):
    project = get_object_or_404(Project, slug=project_slug)
    video = get_object_or_404(Video, project__slug=project_slug,
                                       slug=video_slug)
    values = locals()
    values.update(project.get_perms(request.user))
    return render_to_response('projects/detail_video.html', values,
                               context_instance=RequestContext(request))                
          
          
def detail_screenshot(request, project_slug, screenshot_slug):
    project = get_object_or_404(Project, slug=project_slug)
    screenshot = get_object_or_404(Screenshot, project__slug=project_slug,
                                       slug=screenshot_slug)
    values = locals()
    values.update(project.get_perms(request.user))
    return render_to_response('projects/detail_screenshot.html', values,
                               context_instance=RequestContext(request))        

def detail_poll(request, month, year):
    poll = get_object_or_404(Poll, month=month, year=year)
    return render_to_response('projects/poll_detail.html', {"poll":poll},
                               context_instance=RequestContext(request))        

@login_required
def generic_delete_wrapper(request, model, project_slug, slug, slug_field,
                            **kwargs):
    obj = get_object_or_404(model, **{slug_field:slug,
                                      "project__slug":project_slug})
    if not obj.project.get_perms(request.user)["has_member_perm"]:
        request.user.message_set.create(message=NEED_MEMBER_PERM)
        return HttpResponseRedirect(obj.get_absolute_url())
    return delete_object(request, model, object_id=obj.id, 
                         post_delete_redirect=obj.project.get_absolute_url(),
                         template_name="projects/delete.html",
                         extra_context={"type": obj.__class__.__name__},
                         **kwargs)